module.exports = function (args) {
    const {
        threads,
        TerserPlugin,
        CompressionPlugin,
        CssMinimizerPlugin,
        MiniCssExtractPlugin,
        ImageMinimizerPlugin,
        BundleAnalyzerPlugin
    } = args
    return {
        devtool: 'hidden-source-map',
        plugins: [
            new MiniCssExtractPlugin({
                filename: 'css/[name].[contenthash].css'
            }),
            new CompressionPlugin({
                filename: "[path][base].gz",
                algorithm: "gzip",
                test: /\.js$|\.css$/,
                threshold: 10240,
                minRatio: 0.8,
            }),
            // new BundleAnalyzerPlugin()
        ],
        optimization: {
            minimizer: [
                new TerserPlugin({
                    parallel: threads,
                    terserOptions: {
                        format: {
                            comments: false,
                        },
                    },
                    extractComments: false,
                }),
                new CssMinimizerPlugin(), // css压缩
                new ImageMinimizerPlugin({ // 图片压缩
                    test: /\.(jpe?g|png|gif)$/i,
                    minimizer: {
                        implementation: ImageMinimizerPlugin.imageminMinify,
                        options: {
                            plugins: [
                                ["jpegtran", {progressive: true}],
                                ["optipng", {optimizationLevel: 5}],
                                ["gifsicle", {interlaced: true}],
                            ],
                        },
                        filter: (source) => {
                            return source.byteLength > 10 * 1024
                        },
                    }
                }),
            ],
            runtimeChunk: {
                name: (entrypoint) => {
                    return `runtime~${entrypoint.name}`
                }
            },
            splitChunks: { // https://zhuanlan.zhihu.com/p/687701439?utm_id=0
                chunks: 'all', // 被拆分的chunks类型；async 异步，initial 同步，all 全部
                minSize: 20000, // 被拆分的chunk最小体积,满足这条条件的才会被拆分
                minChunks: 2, // 被拆分的chunk最小被引用次数。例如：a.js 和 b.js 同时引用 c.js , 那么c.js 被拆分出来
                minRemainingSize: 0, // 拆分后剩余的主chunk体积
                /*
                * common1.js export default "common chunk1";
                * common2.js export default "common chunk2";
                * entry-a.js import common1 from './common1';
                * entry-b.js import common1 from './common1'; import common2 from './common2';
                * entry-c.js import common2 from './common2';
                * webpack 在编译时候，由于common1.js 和 common2.js 都被引用两次符合 minChunks = 2 这个条件，所以会拆分common1.js 和 common2.js
                * 现在浏览器请求加载entry-b.js时候，需要同时加载common1.js 和 common2.js 两个文件，故浏览器会并行加载entry-b.js、common1.js、common2.js 三个文件，
                * 如果maxInitialRequests = 2，那么浏览器会并行加载数量是3个文件，不满足maxInitialRequests = 2。
                * 此时，webpack会放弃common1.js 和 common2.js中最小的文件，将其引入到entry-b.js中
                * 注意：maxAsyncRequests（自身不算一个数量） 和 maxInitialRequests（自身算一个数量）
                * */
                maxAsyncRequests: 30,
                maxInitialRequests: 30,
                enforceSizeThreshold: 50000, // 超过这个尺寸的 Chunk 会被强制分包，忽略上述其它 Size 限制
                cacheGroups: {
                    vendors: {
                        test: /[\\/]node_modules[\\/]/,
                        priority: -10,
                        filename: "js/[name].vendors.js",
                        reuseExistingChunk: true,
                    },
                    common: {
                        minChunks: 2,
                        priority: -20,
                        filename: "js/[id].common.js",
                        reuseExistingChunk: true,
                    },
                }
            },
        },
    }
}
